package data

import (
	"UserApp/biz"
	aerrors "UserApp/errors"
	"database/sql"
	"github.com/gin-gonic/gin"
	xerrors "github.com/pkg/errors"
	"gorm.io/gorm"
)

type User struct {
	gorm.Model
	Name    string
	Addr    string
}

type userRepo struct {
	data *Data
}

//类型断言，判断是否正确实现了biz.UserRepo接口
var _ biz.UserRepo = (*userRepo)(nil)

func ProviderUserRepo(d *Data) biz.UserRepo {
	return &userRepo{d}
}

func (r *userRepo)CreateUser(ctx *gin.Context, u biz.User) (biz.User, error) {
	o := User{}
	o.Name = u.Name
	o.Addr = u.Addr
	err := r.data.db.Create(&o).Error

	if err != nil {
		err = xerrors.Wrap(aerrors.Internal(), "GetUser failed")
		return biz.User{}, err
	}

	return biz.User{Id: int64(o.ID), Name: o.Name, Addr: o.Addr}, err
}

func (r *userRepo)GetUser(ctx *gin.Context, uID int64) (biz.User, error) {
	o := User{}
	o.ID = uint(uID)
	err := r.data.db.First(&o).Error
	if err != nil {
		if err.Error() == "record not found" {
			err = xerrors.Wrap(aerrors.NoSqlRow(), "GetUser failed")
		} else {
			err = xerrors.Wrap(aerrors.Internal(), "GetUser failed")
		}
		return biz.User{}, err
	}
	return biz.User{Id: int64(o.ID), Name: o.Name, Addr: o.Addr}, err
}

func (r *userRepo)UpdateUser(ctx *gin.Context, u biz.User) (biz.User, error) {
	o := User{}
	err := r.data.db.First(&o, u.Id).Error
	if err != nil {
		if err == sql.ErrNoRows {
			err = xerrors.Wrap(aerrors.NoSqlRow(), "GetUser failed")
		} else {
			err = xerrors.Wrap(aerrors.Internal(), "GetUser failed")
		}
		return biz.User{}, err
	}

	o.ID = uint(u.Id)
	o.Addr = u.Addr
	o.Name = u.Name
	err = r.data.db.Save(&o).Error
	if err != nil {
		err = xerrors.Wrap(aerrors.Internal(), "GetUser failed")
		return biz.User{}, err
	}

	return biz.User{Id:int64(o.ID), Addr: o.Addr, Name: o.Name}, err
}

func (r *userRepo)DeleteUser(ctx *gin.Context, uID int64) (biz.User, error) {
	o := User{}
	o.ID = uint(uID)
	err := r.data.db.Delete(&o, uID).Error
	if err != nil {
		if err == sql.ErrNoRows {
			err = xerrors.Wrap(aerrors.NoSqlRow(), "GetUser failed")
		} else {
			err = xerrors.Wrap(aerrors.Internal(), "GetUser failed")
		}
		return biz.User{}, err
	}

	return biz.User{Id: int64(o.ID), Name: o.Name, Addr: o.Addr}, err
}


